package com.nebula.core.dsl.operation;

import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.nebula.core.client.NebulaSession;
import com.nebula.core.dsl.WhereStatement;
import com.nebula.core.dsl.builder.LookUpStatementBuilder;
import com.vesoft.nebula.client.graph.data.ResultSet;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * lookup属性查询操作类
 * <p>
 * LOOKUP ON {<vertex_tag> | <edge_type>}
 * [WHERE <expression> [AND <expression> ...]]
 * YIELD [DISTINCT] <return_list> [AS <alias>]
 *
 * @author zhangtao
 */
public class LookUpOperation implements LookUpStatementBuilder.LookUpStatement {
    private List<String> typeList = new ArrayList<>();
    private WhereStatement where;
    private List<SQLSelectItem> selectList = new ArrayList<SQLSelectItem>();
    private NebulaSession nebulaSession;

    private LookUpOperation() {
    }

    private LookUpOperation(NebulaSession nebulaSession) {
        this.nebulaSession = nebulaSession;
    }

    protected static LookUpStatementBuilder.LookUpStart create() {
        return new LookUpOperation();
    }

    protected static LookUpStatementBuilder.LookUpStart create(NebulaSession nebulaSession) {
        return new LookUpOperation(nebulaSession);
    }


    @Override
    public LookUpStatementBuilder.LookUpTypeOut on(String type) {
        this.typeList.add(type);
        return this;
    }

    @Override
    public LookUpStatementBuilder.LookUpWhereOut and(String key, String operator, Object value) {
        if (this.where == null) {
            this.where = WhereStatement.create();
        }
        this.where.and(key, operator, value);
        return this;
    }

    @Override
    public LookUpStatementBuilder.LookUpWhereOut or(String key, String operator, Object value) {
        if (this.where == null) {
            this.where = WhereStatement.create();
        }
        where.or(key, operator, value);
        return this;
    }

    @Override
    public LookUpStatementBuilder.LookUpYieldOut yield(String field, String alias) {
        this.selectList.add(new SQLSelectItem(new SQLIdentifierExpr(field), alias));
        return this;
    }

    @Override
    public LookUpStatementBuilder.LookUpYieldOut yield(String field) {
        this.selectList.add(new SQLSelectItem(new SQLIdentifierExpr(field)));
        return this;
    }

    @Override
    public String build() {
        StringBuilder builder = new StringBuilder("LOOKUP ON ");

        //拼接边类型
        builder.append(typeList.stream().collect(Collectors.joining(",", " ", " ")));

        //拼接where条件
        if (where != null) {
            builder.append(" WHERE ");
            builder.append(where);
        }

        //拼接返回字段
        if (!CollectionUtils.isEmpty(selectList)) {
            builder.append(" YIELD ");
            for (int i = 0; i < selectList.size(); i++) {
                if (i != 0) {
                    builder.append(",");
                }
                selectList.get(i).output(builder);
            }
        }

        return builder.toString();
    }

    @Override
    public ResultSet excute() {
        return nebulaSession.query(this.build());
    }

}